'use strict';

const fs = require('fs');
const path = require('path');
const http = require('http');
const moment = require('moment');
const Koa = require('koa');
const mount = require('koa-mount');
const Router = require('koa-router');
const session = require('koa-session');
const body = require('koa-better-body');
const staticServer = require('koa-static');
const log = require('../services/log/Log');
const {verified} = require('./libs/Token');


function mkDir(err) {
    if (err && err.code !== 'EEXIST') {
        console.error(err.message);
    }
}


function staticDir(dir) {
    return staticServer(path.join(__dirname, dir));
}

async function createServer(port) {
    const app = new Koa();
    const router = new Router();
    const server = http.createServer(app.callback());
    const config = {
        key: 'koa:sess',
        maxAge: 'session',
        overwrite: true,
        httpOnly: true,
        signed: true,
        rolling: false
    };

    app.keys = ['some secret hurr'];
    fs.mkdir('./log', mkDir);

    router.all('*', async function (ctx, next) {
        let start = new Date();
        try {
            let url = ctx.req._parsedUrl.pathname;
            if (url.substr(0, 4) === '/api') {//判断请求路径是api，如果不是说明请求有误
                url = url.substr(4);//去除请求路径中的api
                if (url === '/signIn') {        //判断请求是否为登陆功能如果是跳转到登陆页面
                    let signInAction = require(`../routes/signIn`);
                    await signInAction.apply(ctx, arguments);
                } else {                      //否则的话需要验证header中的权限
                    let _token = ctx.header.authorization;//获取令牌
                    let checkTokenResult = verified(_token);//验证令牌
                    if (!checkTokenResult.success) {  //如果失败则返回失败结果
                        ctx.body = {success: false, message: checkTokenResult.message};
                        return;
                    }
                    let middleware = require(`../routes${url}`);
                    await middleware.apply(ctx, arguments);
                }
            } else {
                ctx.body = {success: false, message: 'path id errror'};
            }
        } catch (err) {
            ctx.body = {success: false, message: err.message};
            let time = moment().format('YYYY-MM-DD HH:mm:ss');
            let errStr =
                `
======================================================================
[${time}]
${err.stack}
`;
            fs.appendFile(`./log/${moment().format('YYYY-MM-DD')}.log`, errStr);

            // TODO 需要根据不同级别的错误使用warn或者error，暂时先全部使用error。
            console.error(`${ctx.method} ${ctx.res.statusCode} ${Date.now() - start}ms ${ctx.originalUrl} ${errStr}`);
        }
    });

    app
        .use(session(config, app))
        .use(log.koa)
        .use(body({
            uploadDir: './upload',
            keepExtensions: true,
            formLimit: "5mb",
            jsonLimit: "5mb",
            textLimit: "5mb"
        }))
        .use(router.routes())
        .use(router.allowedMethods())
        .on('error', function (err, ctx) {
            let time = moment().format('YYYY-MM-DD HH:mm:ss');
            let errStr =
                `
======================================================================
[${time}]
${err.stack}
`;
            fs.appendFile(`./log/${moment().format('YYYY-MM-DD')}.log`, errStr);
            if (ctx) {
                let str = `${ctx.method} ${ctx.res.statusCode} ${ctx.originalUrl} ${errStr}`;
                console.error(str);
            } else {
                console.error(err);
            }
        });
    server.listen(port);
}

async function listen(port) {
    await createServer(port);
}

exports.listen = listen;
